home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #2 / Monster Media No. 2 (Monster Media)(1994).ISO / soundu / tnypl210.zip / MODLOAD.C < prev    next >
C/C++ Source or Header  |  1994-05-22  |  6KB  |  237 lines

  1. /*  modload.c - Tiny MOD Player V2.10 for Watcom C/C++ and DOS/4GW
  2.  
  3.     Module and Sample file loader routines.
  4.  
  5.     Copyright 1993,94 Carlos Hasan
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <conio.h>
  10. #include <malloc.h>
  11. #include <io.h>
  12. #include <fcntl.h>
  13. #include "modplay.h"
  14.  
  15. /* MOD FileFormat */
  16.  
  17. #define ID_MK   0x2E4B2E4D
  18. #define ID_FLT4 0x34544C46
  19. #define ID_6CHN 0x4E484336
  20. #define ID_8CHN 0x4E484338
  21.  
  22. typedef struct {
  23.     byte        SampleName[22];
  24.     word        Length;
  25.     byte        FineTune;
  26.     byte        Volume;
  27.     word        LoopStart;
  28.     word        LoopLength;
  29. } MODSample;
  30.  
  31. typedef struct {
  32.     byte        SongName[20];
  33.     MODSample   Samples[31];
  34.     byte        OrderLength;
  35.     byte        ReStart;
  36.     byte        Orders[128];
  37.     dword       Sign;
  38. } MODHeader;
  39.  
  40. /* MOD PeriodTable */
  41. static word PeriodTable[12*3] = {
  42.     856,808,762,720,678,640,604,570,538,508,480,453,
  43.     428,404,381,360,339,320,302,285,269,254,240,226,
  44.     214,202,190,180,170,160,151,143,135,127,120,113 };
  45.  
  46.  
  47. /* WAV fileformat */
  48.  
  49. #define ID_RIFF 0x46464952
  50. #define ID_WAVE 0x45564157
  51. #define ID_FMT  0x20746D66
  52. #define ID_DATA 0x61746164
  53.  
  54. typedef struct {
  55.     dword   RIFFMagic;
  56.     dword   FileLength;
  57.     dword   FileType;
  58.     dword   FormMagic;
  59.     dword   FormLength;
  60.     word    SampleFormat;
  61.     word    NumChannels;
  62.     dword   PlayRate;
  63.     dword   BytesPerSec;
  64.     word    Pad;
  65.     word    BitsPerSample;
  66.     dword   DataMagic;
  67.     dword   DataLength;
  68. } WAVHeader;
  69.  
  70.  
  71. /* MOD Loader Routine */
  72.  
  73. #define Swap(w) (((dword)(w&0xff))<<8|((dword)(w>>8)))
  74.  
  75. Module *MODLoadModule(char *Path)
  76. {
  77.     int handle,NumTracks,NumPatts,i,j;
  78.     word Note,Period,Inst,Effect;
  79.     dword Length,LoopStart,LoopLength;
  80.     MODHeader Header;
  81.     MODSample *Sample;
  82.     Module *Song;
  83.     byte *Patt;
  84.  
  85.     if ((handle = open(Path,O_RDONLY | O_BINARY)) == -1)
  86.         return NULL;
  87.  
  88.     if (read(handle,&Header,sizeof(Header)) != sizeof(Header)) {
  89.         close(handle);
  90.         return NULL;
  91.     }
  92.  
  93.     if ((Header.Sign == ID_MK) || (Header.Sign == ID_FLT4))
  94.         NumTracks = 4;
  95.     else if (Header.Sign == ID_6CHN)
  96.         NumTracks = 6;
  97.     else if (Header.Sign == ID_8CHN)
  98.         NumTracks = 8;
  99.     else {
  100.         close(handle);
  101.         return NULL;
  102.     }
  103.  
  104.     if ((Song = calloc(1,sizeof(Module))) == NULL) {
  105.         close(handle);
  106.         return NULL;
  107.     }
  108.  
  109.     Song->NumTracks = NumTracks;
  110.     Song->OrderLength = Header.OrderLength;
  111.     for (NumPatts = i = 0; i < 128; i++) {
  112.         Song->Orders[i] = Header.Orders[i];
  113.         if (NumPatts < Header.Orders[i])
  114.             NumPatts = Header.Orders[i];
  115.     }
  116.     NumPatts++;
  117.  
  118.     for (i = 0; i < NumPatts; i++) {
  119.         if ((Song->Patterns[i] = malloc(256*NumTracks)) == NULL) {
  120.             MODFreeModule(Song);
  121.             close(handle);
  122.             return NULL;
  123.         }
  124.         if (read(handle,Song->Patterns[i],256*NumTracks) != 256*NumTracks) {
  125.             MODFreeModule(Song);
  126.             close(handle);
  127.             return NULL;
  128.         }
  129.         for (Patt = Song->Patterns[i], j = 0; j < 64*NumTracks; Patt += 4, j++) {
  130.             Period = ((word)(Patt[0] & 0x0F) << 8) | (Patt[1]);
  131.             Inst = (Patt[0] & 0xF0) | (Patt[2] >> 4);
  132.             Effect = ((word)(Patt[2] & 0x0F) << 8) | (Patt[3]);
  133.             for (Note = 0; Note < 12*3; Note++)
  134.                 if (Period >= PeriodTable[Note]) break;
  135.             if (Note == 12*3) Note = 0; else Note++;
  136.             Patt[0] = Note;
  137.             Patt[1] = Inst;
  138.             Patt[2] = Effect & 0xFF;
  139.             Patt[3] = Effect >> 8;
  140.         }
  141.     }
  142.  
  143.     for (i = 1; i <= 31; i++) {
  144.         Sample = &Header.Samples[i-1];
  145.         if (Sample->Length) {
  146.             Length = Swap(Sample->Length) << 1;
  147.             LoopStart = Swap(Sample->LoopStart) << 1;
  148.             LoopLength = Swap(Sample->LoopLength) << 1;
  149.             if ((Song->SampPtr[i] = malloc(Length)) == NULL) {
  150.                 MODFreeModule(Song);
  151.                 close(handle);
  152.                 return NULL;
  153.             }
  154.             if (read(handle,Song->SampPtr[i],Length) != Length) {
  155.                 MODFreeModule(Song);
  156.                 close(handle);
  157.                 return NULL;
  158.             }
  159.             if (LoopLength <= 2) {
  160.                 Song->SampLoop[i] = Song->SampPtr[i] + Length;
  161.                 Song->SampEnd[i] = Song->SampLoop[i];
  162.             }
  163.             else {
  164.                 Song->SampLoop[i] = Song->SampPtr[i] + LoopStart;
  165.                 Song->SampEnd[i] = Song->SampLoop[i] + LoopLength;
  166.             }
  167.             Song->SampVolume[i] = Sample->Volume;
  168.         }
  169.     }
  170.  
  171.     close(handle);
  172.     return Song;
  173. }
  174.  
  175. void MODFreeModule(Module *Song)
  176. {
  177.     int i;
  178.     if (Song) {
  179.         for (i = 0; i < 128; i++)
  180.             if (Song->Patterns[i]) free(Song->Patterns[i]);
  181.         for (i = 1; i <= 31; i++)
  182.             if (Song->SampPtr[i]) free(Song->SampPtr[i]);
  183.         free(Song);
  184.     }
  185. }
  186.  
  187.  
  188. /* RIFF/WAV Loader Routine */
  189.  
  190. Sample *MODLoadSample(char *Path)
  191. {
  192.     int handle;
  193.     WAVHeader Header;
  194.     Sample *Instr;
  195.     byte *ptr;
  196.     dword len;
  197.  
  198.     if ((handle = open(Path,O_RDONLY | O_BINARY)) == -1)
  199.         return NULL;
  200.     if (read(handle,&Header,sizeof(Header)) != sizeof(Header)) {
  201.         close(handle);
  202.         return NULL;
  203.     }
  204.     if (Header.RIFFMagic != ID_RIFF || Header.FileType != ID_WAVE ||
  205.         Header.FormMagic != ID_FMT || Header.DataMagic != ID_DATA ||
  206.         Header.SampleFormat != 1 || Header.NumChannels != 1 ||
  207.         Header.BitsPerSample != 8) {
  208.         close(handle);
  209.         return NULL;
  210.     }
  211.     if ((Instr = malloc(sizeof(Sample)+Header.DataLength)) == NULL) {
  212.         close(handle);
  213.         return NULL;
  214.     }
  215.     Instr->Period = (8363L*428L)/Header.PlayRate;
  216.     Instr->Volume = 64;
  217.     Instr->Length = Header.DataLength;
  218.     Instr->Data = (byte*)(Instr+1);
  219.     if (read(handle,Instr->Data,Instr->Length) != Instr->Length) {
  220.         free(Instr);
  221.         close(handle);
  222.         return NULL;
  223.     }
  224.     close(handle);
  225.  
  226.     for (ptr = Instr->Data, len = Instr->Length; len; len--)
  227.         *ptr++ ^= 0x80;
  228.  
  229.     return Instr;
  230. }
  231.  
  232. void MODFreeSample(Sample *Instr)
  233. {
  234.     if (Instr) free(Instr);
  235. }
  236.  
  237.